home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / prg_gen / euphor14.zip / MSET.EX < prev    next >
Text File  |  1996-08-27  |  10KB  |  367 lines

  1.         ---------------------------------
  2.         -- Plotting the Mandelbrot Set --
  3.         ---------------------------------
  4. -- Usage: ex mset [filename.dat]
  5. -- e.g. ex mset msetb
  6.  
  7. -- Either generate the initial picture, or redisplay an old one.
  8. -- Hit Enter at any time to stop the display and then hit Enter again 
  9. -- to display a grid. Use the arrow keys to select the most interesting 
  10. -- box in the grid. Hit Enter to enlarge this box to the full size of 
  11. -- the screen, or hit q to quit. The pictures that you display are saved in
  12. -- mseta.dat, msetb.dat, ... You can redisplay them and then put up the 
  13. -- grid and continue zooming in. As you zoom in, black areas are eroded 
  14. -- around the edges, as the iteration count is increased, and we find that
  15. -- points originally believed to be members of the Mset are not members 
  16. -- after all.
  17.  
  18. without type_check
  19.  
  20. include graphics.e
  21. include select.e
  22. include get.e
  23.  
  24. constant GRAPHICS_MODE = 18  -- Try to increase the graphics mode. 
  25.                  -- See euphoria\include\graphics.e
  26.  
  27. constant ZOOM_FACTOR = 20    -- grid size for zooming in
  28.  
  29. constant FALSE = 0, TRUE = 1
  30. constant REAL = 1, IMAG = 2
  31.  
  32. constant ARROW_LEFT  = 331,
  33.      ARROW_RIGHT = 333,
  34.      ARROW_UP    = 328,
  35.      ARROW_DOWN  = 336
  36.  
  37.     -- types --
  38.  
  39. type natural(integer x)
  40.     return x >= 0
  41. end type
  42.  
  43. type complex(sequence x)
  44.     return length(x) = 2 and atom(x[1]) and atom(x[2])
  45. end type
  46.  
  47. procedure beep()
  48. -- make a beep sound
  49.     atom t
  50.  
  51.     t = time()
  52.     sound(500)
  53.     while time() < t + .2 do
  54.     end while
  55.     sound(0)
  56. end procedure
  57.  
  58. natural ncolors
  59. integer max_color, min_color
  60.  
  61. without warning
  62. procedure randomize_palette()
  63. -- choose random color mixtures    
  64.     object prev_mixture 
  65.  
  66.     for i = max_color to min_color by -1 do
  67.     prev_mixture = palette(i, rand(repeat(63, 3)))
  68.     end for
  69.     prev_mixture = palette(0, rand(repeat(63, 3)))
  70. end procedure
  71. with warning
  72.  
  73. natural max_iter
  74.  
  75. sequence vc -- current video configuration
  76.  
  77. procedure grid(sequence x, sequence y, natural color)
  78. -- draw the grid
  79.     atom dx, dy
  80.  
  81.     dx = vc[VC_XPIXELS]/ZOOM_FACTOR
  82.     dy = vc[VC_YPIXELS]/ZOOM_FACTOR
  83.  
  84.     for i = x[1] to x[2] do
  85.     draw_line(color, {{i*dx, y[1]*dy}, {i*dx, y[2]*dy}})
  86.     end for
  87.     for i = y[1] to y[2] do
  88.     draw_line(color, {{x[1]*dx, i*dy}, {x[2]*dx, i*dy}})
  89.     end for
  90. end procedure
  91.  
  92. function zoom()
  93. -- select place to zoom in on next time
  94.     integer key
  95.     sequence box
  96.  
  97.     grid({0, ZOOM_FACTOR}, {0, ZOOM_FACTOR}, 7)
  98.     box = {0, ZOOM_FACTOR-1}
  99.     while TRUE do
  100.     grid({box[1], box[1]+1}, {box[2], box[2]+1}, rand(15))
  101.     key = get_key()
  102.     if key != -1 then
  103.         grid({box[1], box[1]+1}, {box[2], box[2]+1}, 7)
  104.         if key = ARROW_UP then
  105.         if box[2] > 0 then
  106.             box[2] = box[2]-1
  107.         end if
  108.         elsif key = ARROW_DOWN then
  109.         if box[2] < ZOOM_FACTOR-1 then
  110.             box[2] = box[2]+1
  111.         end if
  112.         elsif key = ARROW_RIGHT then
  113.         if box[1] < ZOOM_FACTOR-1 then
  114.             box[1] = box[1]+1
  115.         end if
  116.         elsif key = ARROW_LEFT then
  117.         if box[1] > 0 then
  118.             box[1] = box[1]-1
  119.         end if
  120.         elsif key >= 27  then
  121.         return {}  -- quit
  122.         else
  123.         return {box[1], ZOOM_FACTOR - 1  - box[2]}
  124.         end if
  125.     end if
  126.     end while
  127. end function
  128.  
  129. procedure save_points(integer file, integer rep_count, integer color)
  130. -- We do a bit of image compression here by recording the number of
  131. -- consecutive points of a certain color. Can have up to 256 colors.
  132.     while rep_count > 255 do
  133.     puts(file, 255)
  134.     puts(file, color)
  135.     rep_count = rep_count - 255
  136.     end while
  137.     if rep_count > 0 then
  138.     puts(file, rep_count)
  139.     puts(file, color)
  140.     end if
  141. end procedure
  142.  
  143. function mset(complex lower_left,  -- lower left corner
  144.           complex upper_right) -- upper right corner
  145. -- Plot the Mandelbrot set over some region.
  146. -- The Mandelbrot set is defined by the equation: z = z * z + C
  147. -- where z and C are complex numbers. The starting point for z is 0.
  148. -- If, for a given value of C, z approaches infinity, C is considered to
  149. -- *not* be a member of the set. It can be shown that if the absolute value
  150. -- of z ever becomes greater than 2, then the value of z will increase
  151. -- towards infinity from then on. After a large number of iterations, if
  152. -- the absolute value of z is still less than 2 then we assume with high
  153. -- probability that C is a member of the Mset and this program will show
  154. -- that point in black.
  155.     complex c
  156.     atom zr, zi, zr2, zi2, cr, ci, xsize, ysize
  157.     natural member, stop, color, rep_count, width, height
  158.     natural file_no
  159.     integer pic_save, prev_color
  160.  
  161.     clear_screen()
  162.     height = vc[VC_YPIXELS]
  163.     width = vc[VC_XPIXELS]
  164.     ncolors = vc[VC_NCOLORS]
  165.     xsize = (upper_right[REAL] - lower_left[REAL])/(width - 1)
  166.     ysize = (upper_right[IMAG] - lower_left[IMAG])/(height - 1)
  167.     c = {0, 0}
  168.  
  169.     -- choose a new file to save the picture into
  170.     file_no = 0
  171.     for i = 'a' to 'z' do
  172.     pic_save = open("mset" & i & ".dat", "rb")
  173.     if pic_save = -1 then
  174.         file_no = i
  175.         exit
  176.     else
  177.         -- file exists
  178.         close(pic_save)
  179.     end if
  180.     end for
  181.     if file_no then
  182.     pic_save = open("mset" & file_no & ".dat", "wb")
  183.     else
  184.     puts(1, "Couldn't find a new file name to use\n")
  185.     return 1
  186.     end if
  187.  
  188.     -- save graphics mode and max_iter
  189.     printf(pic_save, "%d ", vc[VC_MODE])
  190.     printf(pic_save, "%d ", max_iter)
  191.     -- save lower_left & upper_right as floating-point sequences
  192.     printf(pic_save, "{%20.15f,%20.15f}", lower_left)
  193.     printf(pic_save, "{%20.15f,%20.15f}", upper_right)
  194.     max_color = -1
  195.     min_color = 99999
  196.     for y = 0 to height - 1 do
  197.     if get_key() != -1 then
  198.         close(pic_save)
  199.         return 0
  200.     end if
  201.     c[IMAG] = upper_right[IMAG] - y * ysize
  202.     prev_color = -1 -- start fresh for each line
  203.     rep_count = 0
  204.     for x = 0 to width - 1 do
  205.         c[REAL] = lower_left[REAL] + x * xsize
  206.         member = TRUE
  207.         zr = 0
  208.         zi = 0
  209.         zr2 = 0
  210.         zi2 = 0
  211.         cr = c[REAL]
  212.         ci = c[IMAG]
  213.         for i = 1 to max_iter do
  214.         zi = 2 * zr * zi + ci
  215.         zr = zr2 - zi2 + cr
  216.         zr2 = zr * zr
  217.         zi2 = zi * zi
  218.         if zr2 + zi2 > 4 then
  219.             member = FALSE
  220.             stop = i
  221.             exit
  222.         end if
  223.         end for
  224.         if member = TRUE then
  225.         color = 0
  226.         else
  227.         color = stop + 51 -- gives nice sequence of colors
  228.         while color >= ncolors do
  229.             color = color - ncolors
  230.         end while
  231.         if color > max_color then
  232.             max_color = color
  233.         end if
  234.         if color < min_color then
  235.             min_color = color
  236.         end if
  237.         end if
  238.         pixel(color, {x, y}) -- also show non-member "bands"
  239.         if color = prev_color then
  240.         rep_count = rep_count + 1
  241.         else
  242.         save_points(pic_save, rep_count, prev_color)
  243.         rep_count = 1
  244.         prev_color = color
  245.         end if
  246.     end for
  247.     -- close off count at end of each line
  248.     save_points(pic_save, rep_count, color)
  249.     end for
  250.     beep()
  251.     close(pic_save)
  252.     return 0
  253. end function
  254.  
  255. procedure view(integer pic_save)
  256. -- redisplay a saved picture file
  257.     integer x, color, rep_count
  258.  
  259.     max_color = -1
  260.     min_color = 99999
  261.     for y = 0 to vc[VC_YPIXELS] - 1 do
  262.     x = 0
  263.     while x < vc[VC_XPIXELS] do
  264.         rep_count = getc(pic_save)
  265.         color = getc(pic_save)
  266.         if rep_count <= 0 then
  267.         return
  268.         end if
  269.         if rep_count = 1 then
  270.         pixel(color, {x, y})  -- faster
  271.         x = x + 1
  272.         else
  273.         draw_line(color, {{x, y}, {x+rep_count-1, y}})
  274.         x = x + rep_count
  275.         end if
  276.         if color != 0 then
  277.         if color > max_color then
  278.             max_color = color
  279.         end if
  280.         if color < min_color then
  281.             min_color = color
  282.         end if
  283.         end if
  284.     end while
  285.     end for
  286. end procedure
  287.  
  288. procedure Mandelbrot()
  289. -- main procedure
  290.     sequence delta, new_box
  291.     complex lower_left, upper_right
  292.     sequence cl, dataname, g
  293.     integer pic_save, mode
  294.  
  295.     cl = command_line()
  296.     if length(cl) >= 3 then
  297.     -- redisplay a saved picture
  298.     dataname = cl[3]
  299.     pic_save = open(dataname, "rb")
  300.     if pic_save = -1 then
  301.         if not find('.', dataname) then
  302.         dataname = dataname & ".dat"
  303.         pic_save = open(dataname, "rb")
  304.         end if
  305.         if pic_save = -1 then
  306.         puts(1, "Couldn't open " & dataname & '\n')
  307.         return
  308.         end if
  309.     end if
  310.     g = {}
  311.     for i = 1 to 4 do
  312.         g = g & get(pic_save)
  313.     end for
  314.     if g[1] != GET_SUCCESS or
  315.        g[3] != GET_SUCCESS or
  316.        g[5] != GET_SUCCESS or
  317.        g[7] != GET_SUCCESS then
  318.         puts(1, "Couldn't read " & dataname & '\n')
  319.         return
  320.     end if
  321.     mode = g[2]
  322.     max_iter = g[4]
  323.     lower_left = g[6]
  324.     upper_right = g[8]
  325.     if graphics_mode(mode) then
  326.     end if
  327.     vc = video_config()
  328.     view(pic_save)
  329.     else
  330.     -- initially show the upper half:
  331.     max_iter = 30 -- increases as we zoom in
  332.     lower_left = {-1, 0}
  333.     upper_right = {1, 1}
  334.     -- set up for desired graphics mode
  335.     if not select_mode(GRAPHICS_MODE) then
  336.         puts(2, "couldn't find a good graphics mode\n")
  337.         return
  338.     end if
  339.     vc = video_config()
  340.     if mset(lower_left, upper_right) then
  341.         return
  342.     end if
  343.     end if
  344.  
  345.     while TRUE do
  346.     while get_key() = -1 do
  347.         randomize_palette()
  348.     end while
  349.     new_box = zoom()
  350.     if length(new_box) = 0 then
  351.         exit
  352.     end if
  353.     delta = (upper_right - lower_left)
  354.     lower_left = lower_left + new_box / ZOOM_FACTOR * delta
  355.     upper_right = lower_left + delta / ZOOM_FACTOR
  356.     max_iter = max_iter * 2  -- need more iterations as we zoom in
  357.     if mset(lower_left,  upper_right) then
  358.         exit
  359.     end if
  360.     end while
  361. end procedure
  362.  
  363. Mandelbrot()
  364.  
  365. if graphics_mode(-1) then
  366. end if
  367.